package game.graphics;

import static org.lwjgl.opengl.GL11.GL_POINTS;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glVertex2i;

import java.io.Serializable;
import java.util.Random;

import application.AutomaticallyUpdatable;
import application.Configuration;

/**
 * Implements simple fire graphic effect.
 * 
 * @author Tomas Zima
 */
public class Fire extends AutomaticallyUpdatable implements Serializable
{
	/**
	 * Constructor.
	 * Save coordinates and size.
	 * 
	 * @param leftDownX
	 * 	Coordinates of left down corner in X axis. It's in pixels
	 *	from the begin of the map.
	 *
	 * @param leftDownY
	 * 	Coordinates of left down corner  in Y axis. It's in pixels
	 * 	from the begin of the map.
	 * 
	 * @param width
	 * 	Width of fire in pixels.
	 * 
	 * @param height
	 * 	Height of fire in pixels.
	 */
	public Fire(int leftDownX, int leftDownY, int width, int height)
	{
		super(20);
		
		// Coordinates and sizes
		this.leftDownX	= leftDownX;
		this.leftDownY	= leftDownY;
		this.width		= width;
		this.height		= height;
		
		// Allocate memory for the algorithm
		this.pixels		= new float[width + 2][height];
		
		// Generate fire
		generateFire();
	}
	
	/**
	 * Pregenerate fire.
	 * Each loop should be different from the previous one (animation).
	 */
	protected void generateFire()
	{
		for (int i = 1; i < width + 1; i++)
		{
			for (int j = height - 1; j >= 0; j--)
			{
				if (j == height - 1 || j == height - 2)
				{
					pixels[i][j] = (float) randomizer.nextInt(1800) / 1000;
				}
				else
				{
					pixels[i][j] = (pixels[i - 1][j + 1] + pixels[i][j + 1] + pixels[i + 1][j + 1] + pixels[i][j + 2]) / 4.0f;
				}
			}
		}
	}
	
	/**
	 * Redraw fire.
	 * It's necessary to set correct coordinates of camera
	 * for the each call, because 2D coordinates for OpenGL
	 * are relative to the coordinates in the map.
	 * 
	 * @param cameraX
	 * 	Coordinates of camera in the X axis.
	 * 
	 * @param cameraY
	 * 	Coordinates of camera in the Y axis.
	 */
	public void redraw(int cameraX, int cameraY)
	{
		refresh();
		
		int relativeLeftDownX = this.leftDownX - cameraX + (Configuration.WINDOW_WIDTH / 2);
		int relativeLeftDownY = this.leftDownY - cameraY + (Configuration.WINDOW_HEIGHT / 2);
		
		glBegin(GL_POINTS);
	
		for (int i = relativeLeftDownX; i < relativeLeftDownX + width; i++)
		{
			for (int j = relativeLeftDownY - height; j < relativeLeftDownY; j++)
			{
				glColor3f(pixels[i - relativeLeftDownX][j - relativeLeftDownY + height], 0.0f, 0.0f);
				glVertex2i(i, j);
			}
		}

		glEnd();
	}
	
	/**
	 * Called by the AutomaticallyUpdatable.
	 */
	@Override
	protected void update()
	{
		generateFire();
	}
	
	private int leftDownX;
	private int leftDownY;
	private int width;
	private int height;

	private float pixels[][];
	
	private Random randomizer = new Random();
}
